/**
  ******************************************************************************
  * File Name          : route_gw_down.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include <string.h>
#include "tskcfg.h"
#include "network.h"
#include "route.h"
#include "cJSON.h"
#include "storage.h"
#include "dwlcd.h"
#include "bsp.h"

static const Route_PayloadType route_to_local_sbtb = {
  .dev_addr  = 0,
  .dev_type  = RT_DV_GW,
  .trans_dir = ROUTE_TRSDIR_NET_TO_LOCAL,
  .pl_type   = ROUTE_PLTYP_GW_SBTB,
  .pl_len    = 0,
  .payload   = {0},
};

/******************************************************************************/
/* {"date":"210706","time":"160551"} */
uint8_t Route_gw_down_time(const char *str, uint8_t len)
{
  const char *p = NULL;
  int v1, v2;
  
  p = strstr(str, "date");
  if(p == NULL)
  {
    return 1;
  }
  
  p += 7;
  
  v1 = atoi(p);
  if((v1 > 991231u) || (v1 < 200101))
	{
		return 2;
	}
	
  v2 = v1 / 10000;
  if((v2 < 20) || (v2 > 99))
  {
    return 3;
  }
  Sys_Adjtime.year = v2;
  
  
  v2 = (v1 / 100) % 100;
  if((v2 < 1) || (v2 > 12))
  {
    return 4;
  }
  Sys_Adjtime.month = v2;
  
  v2 = v1 % 100;
  if((v2 < 1) || (v2 > 31))
  {
    return 5;
  }
  Sys_Adjtime.day = v2;
  
  
  
  p = strstr(str, "time");
  if(p == NULL)
  {
    return 6;
  }
  
  p += 7;
  
  v1 = atoi(p);
  if((v1 > 235959u) || (v1 < 0))
	{
		return 7;
	}
	
  v2 = v1 / 10000;
  if((v2 < 0) || (v2 > 23))
  {
    return 8;
  }
  Sys_Adjtime.hour = v2;
  
  
  v2 = (v1 / 100) % 100;
  if((v2 < 0) || (v2 > 59))
  {
    return 9;
  }
  Sys_Adjtime.minute = v2;
  
  v2 = v1 % 100;
  if((v2 < 0) || (v2 > 59))
  {
    return 10;
  }
  Sys_Adjtime.second = v2;
  
  Sys_SetDataTime(&Sys_Adjtime);
  
  return 0;
}

uint8_t Route_gw_down_sbtb(void)
{
  if(Route_NetToLoc_Qhd != NULL)
  {
    xQueueSend(Route_NetToLoc_Qhd, &route_to_local_sbtb, 0);
    return 0;
  }
	else
  {
    return 1;
  }
}

/* {"date":"2021-07-04","num":"556"} */
uint8_t Route_gw_down_rl(const char *str, uint8_t len)
{
  Storage_SaveType sftype;
  const char *p = NULL;
  int y, m, d, num;
  
  p = strstr(str, "date");
  if(p == NULL)
  {
    return 1;
  }
  
  p += 7;
  
  y = atoi(p)-2000;
  if((y > 99u) || (y < 20))
	{
		return 2;
	}
	
  p = strchr(p, '-');
  if(p == NULL)
  {
    return 3;
  }
  
  p += 1;
  
  m = atoi(p);
	if((m < 1u) || (m > 12))
	{
		return 4;
	}
	
  p = strchr(p, '-');
  if(p == NULL)
  {
    return 5;
  }
  
  p += 1;
  
  d = atoi(p);
  if((d < 1u) || (d > 31))
	{
		return 6;
	}
  
  p = strstr(str, "num");
  if(p == NULL)
  {
    return 7;
  }
  
  p += 6;
  
  num = atoi(p);
  if(num > 0xFFFFu)
  {
    return 8;
  }
  
  if((SysRil_RunPara.year != y) || (SysRil_RunPara.month != m) || (SysRil_RunPara.day != d) || (SysRil_RunPara.clnum != num))
  {
    SysRil_RunPara.year  = y;
    SysRil_RunPara.month = m;
    SysRil_RunPara.day   = d;
    SysRil_RunPara.clnum = num;
    
    SysRil_RunPara.ril = SysRil_Day_diff(SysRil_RunPara.year, SysRil_RunPara.month, SysRil_RunPara.day, \
                                         Sys_Runtime.year, Sys_Runtime.month, Sys_Runtime.day);
    
    DW_Send_rilcl();
    
    sftype = SFLASH_SAVE_SYSRIL;
		if(Storage_qhd != NULL)
		{
			xQueueSend(Storage_qhd, &sftype, 0);
		}
  }
  
  return 0;
}

uint8_t Route_gw_down_addtopo(const char *str, uint8_t len)
{
  Route_PayloadType *proute = NULL;
  
  proute = pvPortMalloc(sizeof(Route_PayloadType));
  if(proute != NULL)
  {
    memset(proute, 0, sizeof(Route_PayloadType));
	
    proute->dev_type  = RT_DV_GW;
    proute->trans_dir = ROUTE_TRSDIR_NET_TO_LOCAL,
    proute->pl_type   = ROUTE_PLTYP_GW_ADDTP,
    proute->pl_len    = sizeof(Route_pl_un_msg_Type);
    
    ((Route_pl_un_msg_Type *)(proute->payload))->msg = 0;
    
    if(strstr(str, "succcess") != NULL)
    {
      ((Route_pl_un_msg_Type *)(proute->payload))->msg = 1;
    }
    
    if(strstr(str, "bound") != NULL)
    {
      ((Route_pl_un_msg_Type *)(proute->payload))->msg = 1;
    }
    
    if(Route_NetToLoc_Qhd != NULL)
    {
      xQueueSend(Route_NetToLoc_Qhd, proute, 0);
    }
	}
	
  vPortFree(proute);
  
  return 0;
}

uint8_t Route_gw_down_deltopo(const char *str, uint8_t len)
{
  Route_PayloadType *proute = NULL;
  
  proute = pvPortMalloc(sizeof(Route_PayloadType));
  if(proute != NULL)
  {
    memset(proute, 0, sizeof(Route_PayloadType));
	
    proute->dev_type  = RT_DV_GW;
    proute->trans_dir = ROUTE_TRSDIR_NET_TO_LOCAL,
    proute->pl_type   = ROUTE_PLTYP_GW_DELTP,
    proute->pl_len    = sizeof(Route_pl_un_msg_Type);
    
    ((Route_pl_un_msg_Type *)(proute->payload))->msg = 0;
    
    if(strstr(str, "succcess") != NULL)
    {
      ((Route_pl_un_msg_Type *)(proute->payload))->msg = 1;
    }
    
    if(strstr(str, "bound") != NULL)
    {
      ((Route_pl_un_msg_Type *)(proute->payload))->msg = 1;
    }
    
    if(Route_NetToLoc_Qhd != NULL)
    {
      xQueueSend(Route_NetToLoc_Qhd, proute, 0);
    }
	}
	
  vPortFree(proute);
  
  return 0;
}

/* {"msg":"success","code":200,"data":[{"productID":"L3XCQ5J2TF","deviceName":"DK50210310001"},{"productID":"uy0K4QMaoN","deviceName":"HK50210310001"}],"id":"1"} */
uint8_t Route_gw_down_gettopo(const char *str, uint8_t len)
{
  uint8_t err = 0;
  uint8_t array_size;
  uint8_t i;
  cJSON *root = NULL;
  cJSON *array = NULL;
  cJSON *array_item = NULL;
  cJSON *msg = NULL;
  cJSON *pid = NULL;
  cJSON *did = NULL;
  Route_DidFormatType didst = {0};
  Route_PayloadType *proute = NULL;
    
  root = cJSON_Parse(str);
  
  msg = cJSON_GetObjectItem(root, "msg");
  if((msg == NULL) || (msg->type != cJSON_String))
  {
    err = 1;
    goto fnout;
  }
  
  if(strstr(msg->valuestring, "success") == NULL)
  {
    err = 2;
    goto fnout;
  }
  
  array = cJSON_GetObjectItem(root, "data");
	if((array == NULL) || (array->type != cJSON_Array))
  {
    err = 3;
    goto fnout;
  }
  
  array_size = cJSON_GetArraySize(array);
  if(array_size > ROUTE_GET_TOPO_MAXNUM)
  {
    err = 4;
    goto fnout;
  }
  
	memset(&Route_NetTopoList, 0, sizeof(Route_ToPoListType));
	
	if(array_size == 0)
	{
		err = 0;
		goto fnout;
	}
  
  for(i=0; i<array_size; i++)
  {
    array_item = cJSON_GetArrayItem(array, i);
    if((array_item == NULL) || (array_item->type != cJSON_Object))
    {
      err = 5;
      goto fnout;
    }
    
    pid = cJSON_GetObjectItem(array_item, "productID");
    if((pid == NULL) || (pid->type != cJSON_String))
    {
      err = 6;
      goto fnout;
    }
    
    did = cJSON_GetObjectItem(array_item, "deviceName");
    if((did == NULL) || (did->type != cJSON_String))
    {
      err = 7;
      goto fnout;
    }
    
    /* 解析并判断拓扑表did的合法性 */
    if(Route_ParseDID(did->valuestring, &didst) != 0)
    {
      err = 8;
      goto fnout;
    }
    
    /* 判断拓扑表中did是否与pid匹配 */
    if(strcmp(Route_str_pids[didst.type], pid->valuestring) != 0)
		{
			err = 9;
      goto fnout;
		}
    
    strncpy(Route_NetTopoList.dids[i], did->valuestring, ROUTE_DID_BUFLEN);
  }
	
  Route_NetTopoList.topo_num = array_size;
  
	err = 0;
	
fnout:
  cJSON_Delete(msg);
  cJSON_Delete(array);
  cJSON_Delete(array_item);
  cJSON_Delete(root);
  cJSON_Delete(pid);
  cJSON_Delete(did);
  
  proute = pvPortMalloc(sizeof(Route_PayloadType));
  if(proute != NULL)
  {
    memset(proute, 0, sizeof(Route_PayloadType));
  
    proute->dev_type  = RT_DV_GW;
    proute->trans_dir = ROUTE_TRSDIR_NET_TO_LOCAL,
    proute->pl_type   = ROUTE_PLTYP_GW_GETTP,
    proute->pl_len    = sizeof(Route_pl_un_msg_Type);
    
    ((Route_pl_un_msg_Type *)(proute->payload))->msg = err;
    
    if(Route_NetToLoc_Qhd != NULL)
    {
      xQueueSend(Route_NetToLoc_Qhd, proute, 0);
    }
  }
  
  vPortFree(proute);
  
  return err;
}

/* {"id":"24","version":"1.0","params":{"cmd":"iiii"}} */
uint8_t Route_gw_cmd(const char *str, uint8_t len)
{
  uint8_t err = 0;
  cJSON *root = NULL;
  cJSON *params = NULL;
  cJSON *msg = NULL;
  char cmdbuf[TTY_RXBUF_MAXLEN];
  
  root = cJSON_Parse(str);
  
  params = cJSON_GetObjectItem(root, "params");
  if(params == NULL)
  {
    err = 1;
    goto cmd_out;
  }
  
  msg = cJSON_GetObjectItem(params, "cmd");
	if((msg == NULL) || (msg->type != cJSON_String))
  {
    err = 2;
    goto cmd_out;
  }
  
  if(strlen(msg->valuestring) >= TTY_RXBUF_MAXLEN)
  {
    err = 3;
    goto cmd_out;
  }
  
  strncpy(cmdbuf, msg->valuestring, TTY_RXBUF_MAXLEN);
  
  if(TTYRecv_qhd != NULL)
  {
    xQueueSend(TTYRecv_qhd, cmdbuf, 0);
  }
  
cmd_out:
  cJSON_Delete(msg);
  cJSON_Delete(params);
  cJSON_Delete(root);
  
  return err;
}
